home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / Macintosh Sample Code / SC.014.CPlusTESample / TESample.cp < prev    next >
Encoding:
Text File  |  1990-04-30  |  11.4 KB  |  483 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------------------
  2.  
  3.     Program:    CPlusTESample 2.0
  4.     File:        TESample.cp
  5.     Uses:       TEDocument.h
  6.                 TESample.h
  7.  
  8.     by Andrew Shebanow
  9.     of Apple Macintosh Developer Technical Support
  10.  
  11.     Copyright © 1989-1990 Apple Computer, Inc.
  12.     All rights reserved.
  13.  
  14. ------------------------------------------------------------------------------------------*/
  15.  
  16. #ifndef __TYPES__
  17. #include <Types.h>
  18. #endif
  19. #ifndef __QUICKDRAW__
  20. #include <QuickDraw.h>
  21. #endif
  22. #ifndef __FONTS__
  23. #include <Fonts.h>
  24. #endif
  25. #ifndef __EVENTS__
  26. #include <Events.h>
  27. #endif
  28. #ifndef __CONTROLS__
  29. #include <Controls.h>
  30. #endif
  31. #ifndef __WINDOWS__
  32. #include <Windows.h>
  33. #endif
  34. #ifndef __MENUS__
  35. #include <Menus.h>
  36. #endif
  37. #ifndef __TEXTEDIT__
  38. #include <TextEdit.h>
  39. #endif
  40. #ifndef __DIALOGS__
  41. #include <Dialogs.h>
  42. #endif
  43. #ifndef __DESK__
  44. #include <Desk.h>
  45. #endif
  46. #ifndef __SCRAP__
  47. #include <Scrap.h>
  48. #endif
  49. #ifndef __TOOLUTILS__
  50. #include <ToolUtils.h>
  51. #endif
  52. #ifndef __MEMORY__
  53. #include <Memory.h>
  54. #endif
  55. #ifndef __SEGLOAD__
  56. #include <SegLoad.h>
  57. #endif
  58. #ifndef __FILES__
  59. #include <Files.h>
  60. #endif
  61. #ifndef __OSUTILS__
  62. #include <OSUtils.h>
  63. #endif
  64. #ifndef __TRAPS__
  65. #include <Traps.h>
  66. #endif
  67. #ifndef __PACKAGES__
  68. #include <Packages.h>
  69. #endif
  70. #ifndef __ERRORS__
  71. #include <Errors.h>
  72. #endif
  73.  
  74. // our class definitions
  75. #include "TEDocument.h"
  76. #include "TESample.h"
  77.  
  78. // ExtremeNeg and ExtremePos are used to set up wide open rectangles and regions.
  79. const short kExtremeNeg = -32768;
  80. const short kExtremePos = 32767 - 1; // required to address an old region bug
  81.  
  82. // kMaxOpenDocuments is used to determine whether a new document can be opened
  83. // or created. We keep track of the number of open documents, and disable the
  84. // menu items that create a new document when the maximum is reached. If the
  85. // number of documents falls below the maximum, the items are enabled again.
  86. const short    kMaxOpenDocuments = 4;
  87.  
  88. const OSType kCreatorType = 'MOOT';
  89.  
  90. // Define max and min macros for efficiency.
  91. #define max(a,b)        ((a) > (b) ? (a) : (b))
  92. #define min(a,b)        ((a) < (b) ? (a) : (b))
  93.  
  94. // Our application object, initialized in main(). We make it
  95. // global so our functions which don't belong to any class
  96. // can find the active document.
  97. TESample* gTheApplication;
  98.  
  99. // main is the entrypoint to the program
  100. int main()
  101. {
  102.     // Create our application object. This MUST be the FIRST thing
  103.     // done in main(), since it initializes the Toolbox for us.
  104.     gTheApplication = new TESample;
  105.     if (gTheApplication == nil)        // if we couldn't allocate object (impossible!?)
  106.       ExitToShell();                // go back to Finder
  107.  
  108.     gTheApplication->ProcessArgs();
  109.  
  110.     // Start our main event loop running. This won't return until user quits
  111.     gTheApplication->EventLoop();
  112.  
  113.     // We always return a value, like good little ANSI worshippers,
  114.     // so that the compiler won't complain
  115.     return 0;
  116. }
  117.  
  118. // the constructor for our class, called automatically when we create
  119. // an instance of this class. In this particular case, we only want
  120. // one instance since the constructor does all the menu setups and
  121. // creates our (untitled) document.
  122. // Note that we call our base TApplication constructor, passing it
  123. // our creator signature constant.
  124. TESample::TESample() : TApplication(kCreatorType)
  125. {
  126.     Handle    menuBar;
  127.  
  128.     // read menus into menu bar
  129.     menuBar = GetNewMBar(rMenuBar);
  130.     // install menus
  131.     SetMenuBar(menuBar);
  132.     DisposHandle(menuBar);
  133.     // add DA names to Apple menu
  134.     AddResMenu(GetMHandle(mApple), 'DRVR');
  135.     DrawMenuBar();
  136.  
  137.     // create empty mouse region
  138.     fMouseRgn = NewRgn();
  139.     // make sure we have a valid cursor region
  140.     AdjustCursor();
  141. }
  142.  
  143. // Tell TApplication class how much heap we need
  144. long TESample::HeapNeeded()
  145. {
  146.     return (kMinSize * 1024);
  147. }
  148.  
  149. // Calculate a sleep value for WaitNextEvent. This takes into account the things
  150. // that DoIdle does with idle time.
  151.  
  152. unsigned long TESample::SleepVal()
  153. {
  154.     unsigned long sleep;
  155.  
  156.     sleep = kMaxSleepTime;                // default value for sleep
  157.     // if we aren't in background, let document tell us how long to sleep
  158.     if ((!fInBackground) && (fCurDoc != nil))
  159.       sleep = min(sleep,fCurDoc->CalcIdle());
  160.     return sleep;
  161. }
  162.  
  163. // This is called whenever we get a null event et al.
  164. // It takes care of necessary periodic actions. For this program,
  165. // it calls TEIdle.
  166.  
  167. void TESample::DoIdle()
  168. {
  169.     TEDocument* fTECurDoc = (TEDocument*) fCurDoc;
  170.  
  171.     if (fTECurDoc != nil)
  172.       fTECurDoc->DoIdle();
  173. } // DoIdle
  174.  
  175. // Change the cursor's shape, depending on its position. This also calculates a
  176. // region that includes the cursor for WaitNextEvent.
  177.  
  178. void TESample::AdjustCursor()
  179. {
  180.     TEDocument* fTECurDoc = (TEDocument*) fCurDoc;
  181.  
  182.     // notice that we don't change cursor if front window isn't ours
  183.     if ( (!fInBackground) && (fTECurDoc != nil) )
  184.       {
  185.         RgnHandle    arrowRgn;
  186.         RgnHandle    iBeamRgn;
  187.         Point        mouse;
  188.  
  189.         // get mouse location and convert to global coordinates
  190.         GetMouse(&mouse);
  191.         LocalToGlobal(&mouse);
  192.  
  193.         // calculate regions for different cursor shapes
  194.         arrowRgn = NewRgn();
  195.         iBeamRgn = NewRgn();
  196.         // start arrowRgn wide open
  197.         SetRectRgn(arrowRgn, kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos);
  198.         // calculate iBeamRgn
  199.         fTECurDoc->GetVisTERgn(iBeamRgn);
  200.         // subtract iBeamRgn from arrowRgn
  201.         DiffRgn(arrowRgn, iBeamRgn, arrowRgn);
  202.  
  203.         // change the cursor and the region parameter
  204.         if (PtInRgn(mouse, iBeamRgn))
  205.           {
  206.             SetCursor(*GetCursor(iBeamCursor));
  207.             CopyRgn(iBeamRgn, fMouseRgn);
  208.           }
  209.         else
  210.           {
  211.             SetCursor(&qd.arrow);
  212.             CopyRgn(arrowRgn, fMouseRgn);
  213.           }
  214.         // get rid of regions we don't need anymore
  215.         DisposeRgn(arrowRgn);
  216.         DisposeRgn(iBeamRgn);
  217.       }
  218. } // AdjustCursor
  219.  
  220. // Enable and disable menus based on the current state. The
  221. // user can only select enabled menu items. We set up all the
  222. // menu items before calling MenuSelect or MenuKey, since
  223. // these are the only times that a menu item can be selected.
  224. // Note that MenuSelect is also the only time the user will
  225. // see menu items. This approach to deciding what enable/
  226. // disable state a menu item has the advantage of
  227. // concentrating all the decision-making in one routine, as
  228. // opposed to being spread throughout the application. Other
  229. // application designs may take a different approach that may
  230. // or may not be as valid.
  231.  
  232. void TESample::AdjustMenus()
  233. {
  234.     WindowPtr    frontmost;
  235.     MenuHandle    fileMenu, editMenu;
  236.     long        offset;
  237.     Boolean        undo;
  238.     Boolean        cutCopyClear;
  239.     Boolean        paste;
  240.     Boolean        save, saveAs;
  241.     Boolean        selectAll;
  242.     TEDocument* fTECurDoc = (TEDocument*) fCurDoc;
  243.  
  244.     frontmost = FrontWindow();
  245.  
  246.     fileMenu = GetMHandle(mFile);
  247.     if (fDocList->NumDocs() < kMaxOpenDocuments)
  248.       {
  249.         // New & Open are enabled when we can open more documents
  250.         EnableItem(fileMenu, iNew);
  251.         EnableItem(fileMenu, iOpen);
  252.       }
  253.     else
  254.       {
  255.         DisableItem(fileMenu, iNew);
  256.         DisableItem(fileMenu, iOpen);
  257.       }
  258.     if (frontmost != (WindowPtr) nil)    // Close is enabled when there is a window to close
  259.       EnableItem(fileMenu, iClose);
  260.     else DisableItem(fileMenu, iClose);
  261.  
  262.     editMenu = GetMHandle(mEdit);
  263.     undo = false;
  264.     cutCopyClear = false;
  265.     paste = false;
  266.     save = saveAs = false;
  267.     selectAll = false;
  268.     if (frontmost != nil)
  269.       {
  270.         selectAll = true;
  271.         if (fCurDoc == nil)
  272.           {
  273.             undo = true;                // all editing is enabled for DA windows
  274.             cutCopyClear = true;
  275.             paste = true;
  276.           }
  277.         else
  278.           {
  279.             // Cut, Copy, and Clear is enabled for app. windows with selections
  280.             if ( fTECurDoc->HaveSelection() )
  281.               cutCopyClear = true;
  282.             // If we have any TEXT in the scrap, enable paste
  283.             if ( GetScrap(nil, 'TEXT', &offset) )
  284.                 paste = true;
  285.             // enable save if we are dirty
  286.             save = fCurDoc->CanSave();
  287.             saveAs = fCurDoc->CanSaveAs();
  288.           }
  289.       }
  290.     if (save)
  291.       EnableItem(fileMenu, iSave);
  292.     else DisableItem(fileMenu, iSave);
  293.     if (saveAs)
  294.       EnableItem(fileMenu, iSaveAs);
  295.     else DisableItem(fileMenu, iSaveAs);
  296.  
  297.     if (undo)
  298.       EnableItem(editMenu, iUndo);
  299.     else DisableItem(editMenu, iUndo);
  300.     if ( cutCopyClear )
  301.       {
  302.         EnableItem(editMenu, iCut);
  303.         EnableItem(editMenu, iCopy);
  304.         EnableItem(editMenu, iClear);
  305.       }
  306.     else
  307.       {
  308.         DisableItem(editMenu, iCut);
  309.         DisableItem(editMenu, iCopy);
  310.         DisableItem(editMenu, iClear);
  311.       }
  312.     if (paste)
  313.       EnableItem(editMenu, iPaste);
  314.     else DisableItem(editMenu, iPaste);
  315.     if (selectAll)
  316.       EnableItem(editMenu, iSelectAll);
  317.     else DisableItem(editMenu, iSelectAll);
  318. } // AdjustMenus
  319.  
  320.  
  321. // This is called when an item is chosen from the menu bar (after calling
  322. // MenuSelect or MenuKey). It does the right thing for each command.
  323.  
  324. void TESample::DoMenuCommand(short menuID, short menuItem)
  325. {
  326.     short        itemHit;
  327.     Str255        daName;
  328.     short        daRefNum;
  329.     WindowPtr    window;
  330.     TEDocument* fTECurDoc = (TEDocument*) fCurDoc;
  331.  
  332.     window = FrontWindow();
  333.     switch ( menuID )
  334.       {
  335.         case mApple:
  336.             switch ( menuItem )
  337.               {
  338.                 case iAbout:        // bring up alert for About
  339.                     itemHit = Alert(rAboutAlert, nil);
  340.                     break;
  341.                 default:            // all non-About items in this menu are DAs et al
  342.                     GetItem(GetMHandle(mApple), menuItem, daName);
  343.                     daRefNum = OpenDeskAcc(daName);
  344.                     break;
  345.               }
  346.             break;
  347.         case mFile:
  348.             switch ( menuItem )
  349.               {
  350.                 case iNew:
  351.                     DoNew();
  352.                     break;
  353.                 case iOpen:
  354.                     DoOpen();
  355.                     break;
  356.                 case iClose:
  357.                     if (fTECurDoc != nil)
  358.                       {
  359.                         // only close the document if the user doesn't cancel
  360.                         if (fTECurDoc->DoClose(true, yesResult, false) != cancelResult)
  361.                           {
  362.                             fDocList->RemoveDoc(fTECurDoc);
  363.                             delete fTECurDoc;
  364.                           }
  365.                       }
  366.                     else CloseDeskAcc(((WindowPeek) fWhichWindow)->windowKind);
  367.                     // make sure our current document/window references are valid
  368.                     fWhichWindow = FrontWindow();
  369.                     if (fWhichWindow != nil)
  370.                       {
  371.                         fCurDoc = fDocList->FindDoc(fWhichWindow);
  372.                         SetPort(fWhichWindow);
  373.                       }
  374.                     else fCurDoc = nil;
  375.                     break;
  376.                 case iSave:
  377.                     if (fTECurDoc != nil)
  378.                       fTECurDoc->DoSave();
  379.                     break;
  380.                 case iSaveAs:
  381.                     if (fTECurDoc != nil)
  382.                       fTECurDoc->DoSaveAs();
  383.                     break;
  384.                 case iQuit:
  385.                     DoQuit(true, yesResult);
  386.                     break;
  387.               }
  388.             break;
  389.         case mEdit:                    // call SystemEdit for DA editing & MultiFinder
  390.             if (!SystemEdit(menuItem-1))
  391.               {
  392.                 switch (menuItem)
  393.                   {
  394.                     case iCut:
  395.                         fTECurDoc->DoCut();
  396.                         break;
  397.                     case iCopy:
  398.                         fTECurDoc->DoCopy();
  399.                         break;
  400.                     case iPaste:
  401.                         fTECurDoc->DoPaste();
  402.                         break;
  403.                     case iClear:
  404.                         fTECurDoc->DoClear();
  405.                         break;
  406.                     case iSelectAll:
  407.                         fTECurDoc->DoSelectAll();
  408.                         break;
  409.                    }
  410.               }
  411.             break;
  412.       }
  413.     HiliteMenu(0);                    // unhighlight what MenuSelect (or MenuKey) hilited
  414. } // DoMenuCommand
  415.  
  416. // Create a new document and window.
  417.  
  418. void TESample::DoNew()
  419. {
  420.     TEDocument* tDoc;
  421.  
  422.     tDoc = new TEDocument(rDocWindow);
  423.     FailNIL(tDoc);
  424.  
  425.     TRY
  426.       {
  427.         tDoc->OpenNewDoc();
  428.         fDocList->AddDoc(tDoc);
  429.       }
  430.     RECOVER
  431.       {
  432.         delete tDoc;
  433.       }
  434.     ENDTRY
  435. } // DoNew
  436.  
  437. void TESample::OpenADoc(short vRefNum, long dirID, StringPtr fName, OSType fType)
  438. {
  439.     if (fType != kTEFileType)
  440.       Failure(eBadFileType,kTEDocErrStrings);
  441.  
  442.     TEDocument* tDoc = new TEDocument(rDocWindow);
  443.     FailNIL(tDoc);
  444.  
  445.     TRY
  446.       {
  447.         CanonicalFileSpec fileSpec;
  448.  
  449.         fileSpec.vRefNum = vRefNum;
  450.         fileSpec.dirID = dirID;
  451.         CopyPString(fileSpec.fileName, fName);
  452.  
  453.         tDoc->OpenOldDoc(fileSpec,false);
  454.         fDocList->AddDoc(tDoc);
  455.       }
  456.     RECOVER
  457.       {
  458.         delete tDoc;
  459.       }
  460.     ENDTRY
  461. }
  462.  
  463. void TESample::DoOpen()
  464. {
  465.     Point where;
  466.     Str255 prompt;
  467.     SFTypeList typeList;
  468.     SFReply reply;
  469.     short vRefNum;
  470.     long dirID;
  471.  
  472.     SetPt(&where,100,100);
  473.     prompt[0] = '\0';
  474.     typeList[0] = kTEFileType;
  475.     SFGetFile(where,prompt,(FileFilterProcPtr) nil,
  476.               1,typeList,(DlgHookProcPtr) nil,&reply);
  477.     if (reply.good == false)
  478.       return;
  479.  
  480.     WDToDirID(reply.vRefNum,vRefNum,dirID);
  481.     OpenADoc(vRefNum,dirID,reply.fName, kTEFileType);
  482. }
  483.